#include <iostream>
#include <pthread.h>
#include <ctime>
#include "RingQueue.hpp"
using namespace std;
#define PNUM 3
#define CNUM 5
string opers = "+-*/%";
template<class T>
class RingQueueInfo
{
public:
    RingQueue<T>* rq_;
    string name_;
};

void* Producter(void* args)
{
    RingQueue<Task>* rq = ((RingQueueInfo<Task>*)args)->rq_;
    string name = ((RingQueueInfo<Task>*)args)->name_;
    while(true)
    {
        //生产数据
        int len = opers.size();
        int x = rand() % 10 + 1;
        usleep(10);
        int y = rand() % 5;
        char op = opers[rand() % len];
        Task t(x, y, op);

        rq->Push(t);

        cout << name << " run, " << t.put_task() << endl;
        sleep(1);
    }
    return nullptr;
}

void* Consumer(void* args)
{
    RingQueue<Task>* rq = ((RingQueueInfo<Task>*)args)->rq_;
    string name = ((RingQueueInfo<Task>*)args)->name_;
    while(true)
    {
        Task t = rq->Pop();

        //处理数据
        t();
        cout << name << " run, " << t.get_result() << endl;
    }
    return nullptr;
}
int main()
{
    srand(time(nullptr) ^ getpid());
    RingQueue<Task>* rq = new RingQueue<Task>();
    pthread_t p[PNUM], c[CNUM];
    
    for(int i = 0; i < PNUM; ++i)
    {
        RingQueueInfo<Task>* info = new RingQueueInfo<Task>();
        info->rq_ = rq;
        info->name_ = "pthread-" + to_string(i + 1);
        pthread_create(p + i, nullptr, Producter, info);
    }
    for(int i = 0; i < CNUM; ++i)
    {
        RingQueueInfo<Task>* info = new RingQueueInfo<Task>();
        info->rq_ = rq;
        info->name_ = "cthread-" + to_string(i + 1);
        pthread_create(p + i, nullptr, Consumer, info);
    }


    for(int i = 0; i < PNUM; ++i)
    {
        pthread_join(p[i], nullptr);
    }
    for(int i = 0; i < CNUM; ++i)
    {
        pthread_join(c[i], nullptr);
        
    }
    return 0;
}